package com.javasea.netty.har.server.netty;

import com.javasea.netty.har.common.cache.ChannelMap;
import com.javasea.netty.har.common.entity.Result;
import com.javasea.netty.har.common.entity.print.Command;
import com.javasea.netty.har.common.utils.Sender;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @ClassName: PrinterServer
 * @Author: huangzf
 * @Date: 2018/8/1 11:53
 * @Description:
 */
@Component
@Slf4j
public class PrinterServer {

    private PtinterServerChannelInitializer serverChannelInitializer = null;

    @Value("${netty.server.port}")
    private int port;

    public void bind() throws Exception {
        //配置服务端的NIO线程组
        // bossGroup: 连接处理
        // workerGroup: 数据发送
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            serverChannelInitializer = new PtinterServerChannelInitializer();
            ServerBootstrap b = new ServerBootstrap();
            // 设置循环线程组事例
            b.group(bossGroup, workerGroup)
                    // 设置channel工厂
                    .channel(NioServerSocketChannel.class)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    // 设置管道
                    .childHandler(serverChannelInitializer);

            //绑定端口，同步等待成功
            ChannelFuture f = b.bind(port).sync();

            //等待服务器监听端口关闭
            f.channel().closeFuture().sync();
        } finally {
            //释放线程池资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public Result queryOnline(Command cmdparam) {
        log.info("cmdparam: " + cmdparam);
        log.info("开始执行命令，获取到的NioClientCode为{}", cmdparam.getNioClientCode());
        Objects.requireNonNull(cmdparam.getNioClientCode(), "NioClientCode不能为空");
        Map<String, Channel> channels = ChannelMap.getMatchChannel(cmdparam.getNioClientCode());
        Set<Map.Entry<String, Channel>> entrySet = channels.entrySet();
        if (channels == null || entrySet.size() == 0) {
            return Result.builder().code(0).message("电脑打印程序未连接").sn(cmdparam.getSn()).nioClientCode(cmdparam.getNioClientCode()).build();
        }
        int count = 0;
        for (Map.Entry<String, Channel> entry : entrySet) {
            count ++;
            String nioClientCodePick = entry.getKey();
            Channel channel = entry.getValue();
            if (channel == null || !channel.isActive()) {
                continue;
            }

            cmdparam.setNioClientCode(nioClientCodePick);
            Sender.send(channel, cmdparam);
            // 清超时的NioClientCode通道
            ChannelMap.removeChannel(nioClientCodePick);
            return Result.builder().code(0).message("打印前查询打印机在线状态超时，请重启打印程序后重新提交打印")
                    .sn(cmdparam.getSn()).nioClientCode(nioClientCodePick).build();
        }
        return Result.builder().code(0).message("打印前未找到在线打印机，请重新提交打印").sn(cmdparam.getSn()).nioClientCode(cmdparam.getNioClientCode()).build();
    }

}

